<template>
  <div class="countdown-container">
    <span :style="computedValueStyle">{{ displayTime }}</span>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'

// 扩展dayjs插件
dayjs.extend(utc)
dayjs.extend(timezone)

// 定义props
const props = defineProps({
  value: {
    type: [Number, Object], // number为时间戳，Object为dayjs对象
    required: true
  },
  format: {
    type: String,
    default: 'HH:mm:ss'
  },
  valueStyle: {
    type: Object,
    default: () => ({})
  },
  timezone: {
    type: String,
    default: 'Asia/Shanghai'
  }
})

// 定义事件
const emit = defineEmits(['finish'])

// 响应式数据
const displayTime = ref('00:00:00')
const isFinished = ref(false)

// 定时器相关变量
let animationFrameId = null
let intervalId = null
let workerTimer = null
let lastUpdateTime = 0
const UPDATE_INTERVAL = 1000 // 1000ms更新一次，提高精度

// 计算样式
const computedValueStyle = computed(() => ({
  fontFamily: 'monospace', // 使用等宽字体确保数字对齐
  ...props.valueStyle
}))

// 获取目标时间的dayjs对象
const getTargetTime = () => {
  if (typeof props.value === 'number') {
    return dayjs(props.value).tz(props.timezone)
  } else if (props.value && typeof props.value === 'object') {
    return dayjs(props.value).tz(props.timezone)
  }
  return null
}

// 格式化时间显示
const formatTime = (duration) => {
  if (duration <= 0) {
    // 倒计时结束，根据format返回对应的零值
    const zeroFormat = props.format
      .replace(/HH|H/g, '00')
      .replace(/mm|m/g, '00')
      .replace(/ss|s/g, '00')
    return zeroFormat
  }

  const hours = Math.floor(duration / (1000 * 60 * 60))
  const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60))
  const seconds = Math.floor((duration % (1000 * 60)) / 1000)

  return props.format
    .replace(/HH/g, hours.toString().padStart(2, '0'))
    .replace(/H/g, hours.toString())
    .replace(/mm/g, minutes.toString().padStart(2, '0'))
    .replace(/m/g, minutes.toString())
    .replace(/ss/g, seconds.toString().padStart(2, '0'))
    .replace(/s/g, seconds.toString())
}

// 更新倒计时显示
const updateCountdown = () => {
  const targetTime = getTargetTime()
  if (!targetTime) return

  const now = dayjs().tz(props.timezone)
  const duration = targetTime.valueOf() - now.valueOf()

  displayTime.value = formatTime(duration)

  // 检查是否完成
  if (duration <= 0 && !isFinished.value) {
    isFinished.value = true
    emit('finish')
    stopTimer()
  }
}

// 高精度定时器 - 使用Web Worker（如果支持）
const createWorkerTimer = () => {
  if (typeof Worker !== 'undefined') {
    try {
      const workerCode = `
        let intervalId;
        self.onmessage = function(e) {
          if (e.data.action === 'start') {
            intervalId = setInterval(() => {
              self.postMessage({ type: 'tick' });
            }, ${UPDATE_INTERVAL});
          } else if (e.data.action === 'stop') {
            if (intervalId) {
              clearInterval(intervalId);
              intervalId = null;
            }
          }
        };
      `
      const blob = new Blob([workerCode], { type: 'application/javascript' })
      workerTimer = new Worker(URL.createObjectURL(blob))

      workerTimer.onmessage = (e) => {
        if (e.data.type === 'tick') {
          updateCountdown()
        }
      }

      return true
    } catch (error) {
      console.warn('Web Worker创建失败，使用备用定时器:', error)
      return false
    }
  }
  return false
}

// 启动定时器
const startTimer = () => {
  stopTimer() // 确保清理之前的定时器

  // 立即更新一次
  updateCountdown()

  // 尝试使用Web Worker定时器
  if (createWorkerTimer()) {
    workerTimer.postMessage({ action: 'start' })
  } else {
    // 备用方案：使用requestAnimationFrame + setInterval组合
    const tick = () => {
      const now = performance.now()
      if (now - lastUpdateTime >= UPDATE_INTERVAL) {
        updateCountdown()
        lastUpdateTime = now
      }
      if (!isFinished.value) {
        animationFrameId = requestAnimationFrame(tick)
      }
    }

    // 同时使用setInterval作为备用
    intervalId = setInterval(updateCountdown, UPDATE_INTERVAL)
    animationFrameId = requestAnimationFrame(tick)
  }
}

// 停止定时器
const stopTimer = () => {
  // 清理Web Worker定时器
  if (workerTimer) {
    workerTimer.postMessage({ action: 'stop' })
    workerTimer.terminate()
    workerTimer = null
  }

  // 清理requestAnimationFrame
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
    animationFrameId = null
  }

  // 清理setInterval
  if (intervalId) {
    clearInterval(intervalId)
    intervalId = null
  }
}

// 页面可见性变化处理 - 防止后台运行时计时不准
const handleVisibilityChange = () => {
  if (document.hidden) {
    // 页面隐藏时记录时间
    localStorage.setItem('countdown_hidden_time', Date.now().toString())
  } else {
    // 页面显示时重新校准
    const hiddenTime = localStorage.getItem('countdown_hidden_time')
    if (hiddenTime) {
      localStorage.removeItem('countdown_hidden_time')
      // 立即更新显示，确保时间准确
      updateCountdown()
    }
  }
}

// 监听props变化
watch(() => props.value, () => {
  isFinished.value = false
  startTimer()
}, { immediate: false })

watch(() => props.timezone, () => {
  updateCountdown()
})

// 生命周期钩子
onMounted(() => {
  // 添加页面可见性监听
  document.addEventListener('visibilitychange', handleVisibilityChange)

  // 添加窗口焦点监听
  window.addEventListener('focus', updateCountdown)

  startTimer()
})




onUnmounted(() => {
  stopTimer()

  // 清理事件监听
  document.removeEventListener('visibilitychange', handleVisibilityChange)
  window.removeEventListener('focus', updateCountdown)

  // 清理localStorage
  localStorage.removeItem('countdown_hidden_time')
})
</script>

<style scoped>
.countdown-container {
  display: inline-block;
}
</style>
